/*
 * crc.cc
 *
 *  Created on: 2011-1-4
 *      Author: xuhui
 */

#include "crc.h"

#define POLYNOMIAL8 0

//#define POLYNOMIAL16 0x4005
/*
 *CRC-16-CCITT x16 + x12 + x5 + 1
 *http://en.wikipedia.org/wiki/Cyclic_redundancy_check
 */
#define POLYNOMIAL16 0x1021

static uint8_t crc8_table[256];

static uint16_t crc16_table[256];

static void gen_crc8_table(void){
	int i, j;
	uint8_t crc_accum;
	for ( i = 0;  i < 256;  i++ ){
		crc_accum = (uint8_t) i ;
		for ( j = 0;  j < 8;  j++ ){
			if ( crc_accum & 0x80 )
				crc_accum = ( crc_accum << 1 ) ^ POLYNOMIAL8;
			else
				crc_accum =( crc_accum << 1 );
		}
		crc8_table[i] = crc_accum; }
	return;
}

static void gen_crc16_table(void){
	int i, j;
	uint16_t crc_accum;
	for ( i = 0;  i < 256;  i++ ){
		crc_accum = (uint16_t) i << 8;
		for ( j = 0;  j < 8;  j++ ){
			if ( crc_accum & 0x8000 )
				crc_accum = ( crc_accum << 1 ) ^ POLYNOMIAL16;
			else
				crc_accum =( crc_accum << 1 );
		}
		crc16_table[i] = crc_accum;
	}
	return;
}

uint16_t update_crc16(
		uint16_t crc_accum,
		const char *data_blk_ptr,
		int data_blk_size){
	int i, j;
	static int initialized = 0;
	if(initialized == 0){
		initialized = 1;
		gen_crc16_table();
	}
	for ( j = 0;  j < data_blk_size;  j++ ){
		i = ( (uint16_t) ( crc_accum >> 8) ^ *data_blk_ptr++ ) & 0xff;
		crc_accum = ( crc_accum << 8 ) ^ crc16_table[i];
	}
	return crc_accum;
}
